from fill_in_error import __, assert_equal

# dict stands for dictionary or map

# IMPORTANT:
# suppose a list is function(mapping) from 0,1,2... to objects
# then dict is function(mapping) from objects(key) to objects(value) !!!
# so we say dict is a container to gather (key, value) pairs

class AboutDict:
    def create_an_empty_dict():
        new_dict = {}
        assert_equal(new_dict, __)

    def or_this_way():
        new_dict = dict()
        assert_equal(new_dict, __)

    def create_a_diect_with_some_value():
        # normal form
        fruit_price = {'banana': 2, 'apple': 3, 'pear': 1}
        assert_equal(fruit_price, __)

        # remember, dict is unordered!
        assert_equal({1: 2, 2: 3}, {2: 3, 1: 2})

        # some magic
        new_dict = {x: x+1 for x in range(3)}
        assert_equal(new_dict, __)
        
    def len_of_a_dict():
        new_dict = {}
        assert_equal(len(new_dict), __)
        
        new_dict = {x: x for x in range(3)}
        assert_equal(len(new_dict), __)
        
    def get_value_of_a_given_key():
        new_dict = {x: x for x in range(3)}
        assert_equal(new_dict, __)

        assert_equal(new_dict[0], __)

        fruit_price = {'banana': 2, 'apple': 3, 'pear': 1}

        assert_equal(fruit_price['banana'], __)
        # if the key does not exist, KeyError will be thrown
        # uncomment the following code to see what happened

        # assert_equal(fruit_price['watermelon'], __)

        # you can use fruit_price.get to access element, too
        assert_equal(fruit_price.get('banana'), __)
        
        # get returns None if the key is not exist
        assert_equal(fruit_price.get('watermelon'), __)

    def modify_or_add_to_a_dict():
        fruit_price = {'banana': 2, 'apple': 3, 'pear': 1}
        assert_equal(fruit_price['banana'], __)
        fruit_price['banana'] = 3
        assert_equal(fruit_price['banana'], __)
        
        assert_equal(fruit_price.get('watermelon'), __)
        fruit_price['watermelon'] = 10
        assert_equal(fruit_price['watermelon'], __)
        
    def pop_removes_a_key_return_value():
        fruit_price = {'banana': 2, 'apple': 3, 'pear': 1}
        assert_equal(fruit_price.pop('banana'), __)
        assert_equal(fruit_price, __)
        
    def get_keys():
        # fruit_price.keys() returns all keys of the dict
        # however, you need to wrapped it with list()
        # to get a list of keys
        fruit_price = {'banana': 2, 'apple': 3, 'pear': 1}
        keys_of_fruit = list(fruit_price.keys())
        assert_equal(keys_of_fruit, __)
        
    def get_values():
        # the function is has similar effect as get_keys
        fruit_price = {'banana': 2, 'apple': 3, 'pear': 1}
        values_of_fruit = list(fruit_price.values())
        assert_equal(values_of_fruit, __)

        new_dict = {1:2, 3:2}
        values_of_dict = list(new_dict.values())
        assert_equal(values_of_dict, __)
        
    def get_items():
        # an item is a (key, value)
        fruit_price = {'banana': 2, 'apple': 3, 'pear': 1}
        items_of_fruit = list(fruit_price.items())
        assert_equal(items_of_fruit, __)

